/******************************************************************************
 * Copyright (C) 2011 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.logback;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Timestamp;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.classic.spi.ThrowableProxyUtil;

/**
 * @author 周振兴
 * @since 1.0
 * @version 2011-2-28 周振兴
 */
public class LoggingEventBsonifierImpl implements ILoggingEventBsonifier {
    
    /**
     * 封装vo对象
     * 
     * @param loggingEvent 日志记录事件
     * @return 日志记录事件实体对象
     * @see com.comtop.top.component.common.logback.ILoggingEventBsonifier#bsonify(ch.qos.logback.classic.spi.ILoggingEvent)
     */
    public LoggingEventVO bsonify(ILoggingEvent loggingEvent) {
        LoggingEventVO objLoggingEventVO = null;
        if (loggingEvent != null) {
            StringBuilder sbMessage = new StringBuilder();
            objLoggingEventVO = new LoggingEventVO();
            objLoggingEventVO.setUpdateTime(new Timestamp(loggingEvent.getTimeStamp()));
            objLoggingEventVO.setLevel(loggingEvent.getLevel().toString());
            objLoggingEventVO.setThread(loggingEvent.getThreadName());
            sbMessage.append(loggingEvent.getFormattedMessage());
            
            objLoggingEventVO.setLoggerName(loggingEvent.getLoggerName());
            
            StackTraceElement[] objStackTraceElements = loggingEvent.getCallerData();
            StackTraceElement objCallerData = objStackTraceElements[0];
            if (objCallerData != null) {
                objLoggingEventVO.setCallerFilename(objCallerData.getFileName());
                objLoggingEventVO.setCallerClass(objCallerData.getClassName());
                objLoggingEventVO.setCallerMethod(objCallerData.getMethodName());
                objCallerData.getLineNumber();
                objLoggingEventVO.setCallerLine(objCallerData.getLineNumber());
            }
            // addLocationInformation(result, loggingEvent.getLocationInformation());
            addThrowableInformation(loggingEvent, sbMessage);
            objLoggingEventVO.setMessage(sbMessage.toString());
            try {
                InetAddress objAddress = InetAddress.getLocalHost();
                objLoggingEventVO.setMachine(objAddress.getHostAddress());
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        return objLoggingEventVO;
    }
    
    /**
     * 添加异常信息
     * 
     * @param loggingEvent 日志事件
     * @param sb 拼装消息字符串
     */
    private void addThrowableInformation(ILoggingEvent loggingEvent, StringBuilder sb) {
        IThrowableProxy objThrowableProxy = loggingEvent.getThrowableProxy();
        if (objThrowableProxy != null) {
            String strMessage = objThrowableProxy.getMessage();
            sb.append("\n" + objThrowableProxy.getClassName() + ":" + strMessage + "\n");
            StackTraceElementProxy[] objStackTraceElementProxyArray = objThrowableProxy.getStackTraceElementProxyArray();
            for (int i = 0, iSize = objStackTraceElementProxyArray.length; i < iSize; i++) {
                sb.append(objStackTraceElementProxyArray[i].getSTEAsString());
                sb.append("\n");
            }
        }
    }
    
    /**
     * @param loggingEvent 日志事件
     * @param sb 拼装消息字符串
     */
    protected void addThrowable(ILoggingEvent loggingEvent, StringBuilder sb) {
        IThrowableProxy objProxy = loggingEvent.getThrowableProxy();
        for (; objProxy != null; objProxy = objProxy.getCause()) {
            StringBuilder sbBuf = new StringBuilder();
            ThrowableProxyUtil.printFirstLine(sbBuf, objProxy);
            int iCommonFrames = objProxy.getCommonFrames();
            StackTraceElementProxy objStepArray[] = objProxy.getStackTraceElementProxyArray();
            for (int i = 0; i < objStepArray.length - iCommonFrames; i++) {
                sb.append('\t');
                ThrowableProxyUtil.printSTEP(sb, objStepArray[i]);
            }
            
            if (iCommonFrames > 0) {
                sb.append('\t').append("... ").append(iCommonFrames).append(" common frames omitted");
            }
        }
    }
}